﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using Project5.Models;
using Project5.DAL;
using System.Xml;
using System.IO;
using System.Net;
using System.Text;
using System.Xml.Linq;

namespace Project5.Controllers
{
    public class SurveyController : Controller
    {
        private ISurveyDAL surveyDAL = new SurveyDAL();

        //
        // GET: /Survey/

        public ActionResult Create()
        {
            SurveyModel model = new SurveyModel();
            model.Originator = User.Identity.Name;
            model.State = 0; //Start it in the "under work" phase
            model.Name = "Untitled Survey";
            model.Monetized = false;
            model = surveyDAL.Add(model);
            return RedirectToAction("../Survey//Edit//" + model.Id);
        }

        public ActionResult Edit(int id)
        {
            var model = surveyDAL.FindAllQuestionsEager(id);
            SurveyModel smodel = surveyDAL.FindSurvey(id);
            ViewBag.id = id;
            ViewBag.SurveyName = smodel.Name;
            ViewBag.SurveyOriginator = smodel.Originator;
            ViewBag.Questions = model;
            ViewBag.Monetized = smodel.Monetized;
            if (smodel.Originator.Equals(User.Identity.Name, StringComparison.Ordinal))
                return View();
            //else return RedirectToAction("../Home//Index");
            else return RedirectToAction("Index", "Home");
        }

        [HttpPost]
        public ActionResult Edit(SurveyModel model)
        {
            return View(model);
        }

        public ActionResult CreateQuestion(int id)
        {
            SurveyModel model = surveyDAL.FindSurvey(id);
            QuestionModel nextmod = new QuestionModel
            {
                SurveyId = id,
            };
            ViewBag.SurveyId = id;
            return View(nextmod);
        }

        [HttpPost]
        public ActionResult CreateQuestion(QuestionModel qmodel)
        {
            if (ModelState.IsValid)
            {
                //If we have a T/F Question, just make it a mult choice w/ choices "True" and "False"
                if (qmodel.Type == 3) 
                {
                    qmodel = SetTrueAndFalseChoices(qmodel);
                }
                //first, add it to the database of questions
                qmodel = surveyDAL.Add(qmodel);
            }
            return Json(qmodel);
        }

        private QuestionModel SetTrueAndFalseChoices(QuestionModel qmodel)
        {
            qmodel.Choices = new List<ChoiceModel>();
            ChoiceModel trueChoice = new ChoiceModel
            {
                QuestionId = qmodel.Id,
                Choice = "True",
            };
            ChoiceModel falseChoice = new ChoiceModel
            {
                QuestionId = qmodel.Id,
                Choice = "False",
            };

            qmodel.Choices.Add(trueChoice);
            qmodel.Choices.Add(falseChoice);

            return qmodel;
        }

        [HttpPost]
        public bool UpdateQuestion(QuestionModel model)
        {
            bool updated = false;
            if (ModelState.IsValid)
            {
                QuestionModel oldModel = surveyDAL.FindQuestionEager(model.Id);
                if ( (oldModel.Type == 1) && (model.Type == 3) )
                {
                    model = SetTrueAndFalseChoices(model);
                }
                if ((oldModel.Type == 2 || oldModel.Type == 3) && model.Type == 1)
                {
                    surveyDAL.DeleteChoices(oldModel.Choices);
                    model.Choices = new List<ChoiceModel>();
                }
                updated = surveyDAL.Update(model, oldModel);
            }
            return updated;
        }
        
        [HttpPost]
        public void Delete(int id)
        {
            surveyDAL.Delete(id);
        }

        [HttpPost]
        public void DeleteQuestion(int id)
        {
            surveyDAL.DeleteQuestion(id);
        }

        [HttpPost]
        public void DeleteChoice(int id)
        {
            surveyDAL.DeleteChoice(id);
        }

        [HttpPost]
        public void SaveResponse(int id, string newResponse, int sessionId)
        {
            var model = surveyDAL.FindAllQuestions(id);
            QuestionModel qmodel = surveyDAL.FindQuestion(id);
            ResponseModel rmodel = surveyDAL.FindResponseByQuestionAndSessionId(qmodel.Id, sessionId);
            if (rmodel == null)
            {
                ResponseModel newrmodel = new ResponseModel
                {
                    QuestionId = id,
                    SurveyId = qmodel.SurveyId,
                    Response = newResponse,
                    sessionId = sessionId,
                    Type = qmodel.Type,
                    QuestionText = qmodel.Question,

                };
                surveyDAL.Add(newrmodel);
            }
            else
            {
                rmodel.Response = newResponse;
                surveyDAL.updateResponse(rmodel);
            }

        }

        public ActionResult Details(int id)
        {
            SurveyModel model = surveyDAL.FindSurvey(id);
            ViewBag.id = id;
            ViewBag.SurveyName = model.Name;
            ViewBag.SurveyOriginator = model.Originator;

            var models = surveyDAL.FindAllResponses(model);
            /***if (models == null)
            {
                models = new List<ResponseModel> { };
                ResponseModel response1 = new ResponseModel();
                response1.Id = 0;
                response1.QuestionId = 1;
                response1.Response = "Hello";
                response1.SurveyId = id;

                ResponseModel response2 = new ResponseModel();
                response2.Id = 1;
                response2.QuestionId = 2;
                response2.Response = "Question 2 response";
                response2.SurveyId = id;

                models.Add(response1);
                models.Add(response2);
                
            }***/
            return View(models);
        }
        
        [HttpPost]
        public string Rename(int id, string newName)
        {
            string returnValue = "ERROR";
            if (newName != null && !string.IsNullOrEmpty(newName.Trim()))
            {
                returnValue = "Survey: ";
                returnValue += surveyDAL.RenameSurvey(id, newName);
            }
            return returnValue;
        }

        [HttpPost]
        public bool SetMonetized(int id, string monetizedVal)
        {
            bool returnValue = false;
            bool mon = (monetizedVal == "True");
            returnValue = surveyDAL.SetMonetized(id, mon);
            return returnValue;
        }

        public ActionResult Action(int id)
        {
            SurveyModel model = surveyDAL.FindSurvey(id);
            surveyDAL.actionSurvey(id, model.State + 1);
            model.View = 1;
            surveyDAL.AddProctor(model.Originator, model.Id);
            return RedirectToAction("../Home//Index");

        }

        public ActionResult Take(int id)
        {
            var model = surveyDAL.FindAllQuestionsEager(id);
            SurveyModel smodel = surveyDAL.FindSurvey(id);
            ViewBag.id = id;
            ViewBag.SurveyModel = smodel;
            ViewBag.Questions = model;
            ViewBag.UserName = User.Identity.Name;
            ViewBag.proctors = surveyDAL.FindAllProctors(id);
            int seed = unchecked(DateTime.Now.Ticks.GetHashCode());
            Random randomSessionId = new Random(seed);
            ViewBag.SessionId = randomSessionId.Next();
            return View();

        }

        [HttpPost]
        public void AddProctorToSurvey(int id, string name)
        {
            surveyDAL.AddProctor(name, id);
        }

        // Get: /Survey/Payment
        public ActionResult Payment()
        {
            return View();
        }

        //
        // POST: /Survey/Payment
        [HttpPost]
        public ActionResult Payment(PaymentModel model)
        {
            surveyDAL.Add(model, User.Identity.Name);
            return View(model);
        }

        
        [HttpPost]
        public HttpStatusCode Pay()
        {
            HttpStatusCode returnCode = HttpStatusCode.NoContent;
            PaymentModel payinfo = surveyDAL.FindPaymentInfo(User.Identity.Name);
            //PayPal API Credentials
            string API_UserName = payinfo.PayPalUsername;// "joseph_1354586086_biz_api1.marquette.edu"; //TODO
            string API_Password = payinfo.PayPalPassword; //"1354586135"; //TODO
            string API_Signature = payinfo.PayPalSignature;// "AyyCWzA-aL6osV3t1GyNQ6aMhzYIA7LGYZPrIdanK4NOXMBaN6dTIZ6X"; //TODO
            string API_AppID = payinfo.PayPalId;// "APP-80W284485P519543T"; //TODO: Default App ID for Sandbox
            string API_SenderEmail = payinfo.PayPalEmail;// "joseph_1354586086_biz@marquette.edu"; //TODO
            string API_RequestFormat = "JSON";
            string API_ResponseFormat = "XML";
            string API_DeviceIP = "134.48.7.215";

            //Initialize the pay request values
            string actionType = "PAY";
            string receiverEmail = "joseph_1353913056_per@marquette.edu";
            string receiverAmount = payinfo.PaymentAmount.ToString("0.00");
            string currencyCode = "USD";
            string feesPayer = "SENDER";
            string cancelUrl = "http://www.google.com"; //"~/Home/Index";
            string returnUrl = "http://www.google.com"; //"~/Home/Index";
            

            //url
            string url = "https://svcs.sandbox.paypal.com/AdaptivePayments/Pay";

            //format data for http request
            string data1 = "{\"actionType\":\"" + actionType + "\",";
            string data2 = "\"cancelUrl\":\"" + cancelUrl + "\",";
            string data3 = "\"currencyCode\":\"" + currencyCode + "\",";
            string data4 = "\"feesPayer\":\"" + feesPayer + "\",";
            string data5 = "\"returnUrl\":\"" + returnUrl + "\",";
            string data6 = "\"requestEnvelope\":{\"errorLanguage\":\"en_US\",\"detailLevel\":\"ReturnAll\"},";
            string data7 = "\"receiverList\":{\"receiver\":[{\"email\":\"" + receiverEmail + "\",\"amount\":\"" + receiverAmount + "\"}]}},";
            string data8 = "\"senderEmail\":\"" + API_SenderEmail + "\"";

            //create POST data and convert it to a byte array.
            string data = data1 + data2 + data3 + data4 + data5 + data6 + data7 + data8;
            byte[] byteArray = Encoding.UTF8.GetBytes(data);

            //open an http request with paypal.com
            System.Net.WebRequest request = System.Net.WebRequest.Create(url);

            //set the header for the http request
            request.Headers.Add("X-PAYPAL-REQUEST-DATA-FORMAT", API_RequestFormat);
            request.Headers.Add("X-PAYPAL-RESPONSE-DATA-FORMAT", API_ResponseFormat);
            request.Headers.Add("X-PAYPAL-SECURITY-USERID", API_UserName);
            request.Headers.Add("X-PAYPAL-SECURITY-PASSWORD", API_Password);
            request.Headers.Add("X-PAYPAL-SECURITY-SIGNATURE", API_Signature);
            request.Headers.Add("X-PAYPAL-APPLICATION-ID", API_AppID);
            request.Headers.Add("X-PAYPAL-DEVICE-IPADDRESS", API_DeviceIP);

            //Specify http request parameters
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.Credentials = CredentialCache.DefaultCredentials;
            request.ContentLength = byteArray.Length;

            // Get the request stream.
            Stream dataStream = request.GetRequestStream();
            // Write the data to the request stream.
            dataStream.Write(byteArray, 0, byteArray.Length);
            // Close the Stream object.
            dataStream.Close();
            // Get the response.
            WebResponse response = request.GetResponse();
            // Display the status.
            Console.WriteLine(((HttpWebResponse)response).StatusDescription);
            // Get the stream containing content returned by the server.
            dataStream = response.GetResponseStream();
            // Open the stream using a StreamReader for easy access.
            StreamReader reader = new StreamReader(dataStream);
            // Read the content.
            string responseFromServer = reader.ReadToEnd();
            // Display the content.
            XElement xmlTree = XElement.Parse(responseFromServer);
            string ack ="";
            string payStatus ="";
            foreach (XElement e in xmlTree.DescendantsAndSelf())
            {
                if (Equals(e.Name.LocalName, "ack"))
                {
                    ack = e.Value;
                }
                else if (Equals(e.Name.LocalName, "paymentExecStatus"))
                {
                    payStatus = e.Value;
                }
            }

            if (Equals(ack, "Success") && Equals(payStatus, "CREATED"))
            {
                returnCode = HttpStatusCode.Created;
            }

            // Clean up the streams.
            reader.Close();
            dataStream.Close();
            response.Close();
            return returnCode;
        }
    }
}